Xen Security Modules: XSM
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 31 Aug 2007 10:21:35 +0000 (11:21 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 31 Aug 2007 10:21:35 +0000 (11:21 +0100)
Signed-off-by: George Coker <gscoker@alpha.ncsc.mil>
31 files changed:
Config.mk
xen/Makefile
xen/Rules.mk
xen/arch/x86/domctl.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/mm.c
xen/arch/x86/mm/paging.c
xen/arch/x86/physdev.c
xen/arch/x86/platform_hypercall.c
xen/arch/x86/setup.c
xen/arch/x86/sysctl.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_32/xen.lds.S
xen/arch/x86/x86_64/entry.S
xen/common/domain.c
xen/common/domctl.c
xen/common/event_channel.c
xen/common/grant_table.c
xen/common/kexec.c
xen/common/memory.c
xen/common/schedule.c
xen/common/sysctl.c
xen/common/xenoprof.c
xen/drivers/char/console.c
xen/include/public/xen.h
xen/include/xen/hypercall.h
xen/include/xsm/xsm.h [new file with mode: 0644]
xen/xsm/Makefile [new file with mode: 0644]
xen/xsm/dummy.c [new file with mode: 0644]
xen/xsm/xsm_core.c [new file with mode: 0644]
xen/xsm/xsm_policy.c [new file with mode: 0644]

index 16d6360cef8129b82605395baa6abc2dc64ab102..9a5b7e7e791a8ae632ca063886640d5911bef04e 100644 (file)
--- a/Config.mk
+++ b/Config.mk
@@ -78,10 +78,12 @@ CFLAGS     += $(call cc-option,$(CC),-Wdeclaration-after-statement,)
 LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i)) 
 CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
 
+# Enable XSM security module.  Enabling XSM requires selection of an 
+# XSM security module.
+XSM_ENABLE ?= n
+
 # If ACM_SECURITY = y, then the access control module is compiled
 # into Xen and the policy type can be set by the boot policy file
-#        y - Build the Xen ACM framework
-#        n - Do not build the Xen ACM framework
 ACM_SECURITY ?= n
 
 # Optional components
index b0a9ac311c74165a95763ded7c0c50d1e69fec83..456003ebb9c84d821e63800642f68a859fd953c5 100644 (file)
@@ -56,6 +56,7 @@ _clean: delete-unfresh-files
        $(MAKE) -f $(BASEDIR)/Rules.mk -C common clean
        $(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean
        $(MAKE) -f $(BASEDIR)/Rules.mk -C acm clean
+       $(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
        $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
        rm -f include/asm *.o $(TARGET)* *~ core
        rm -f include/asm-*/asm-offsets.h
@@ -122,7 +123,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
 build-headers:
        $(MAKE) -C include/public/foreign
 
-SUBDIRS = acm arch/$(TARGET_ARCH) common drivers 
+SUBDIRS = xsm acm arch/$(TARGET_ARCH) common drivers
 define all_sources
     ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \
       find include -name 'asm-*' -prune -o -name '*.h' -print; \
index 55ae9746e08e7a119a9f9a30e12b42a5f5e7aa5b..dd78419dea8ef8a67a0410b59478d5ba68e82074 100644 (file)
@@ -52,10 +52,12 @@ HDRS  := $(filter-out %/asm-offsets.h,$(AHDRS))
 # Note that link order matters!
 ALL_OBJS-y               += $(BASEDIR)/common/built_in.o
 ALL_OBJS-y               += $(BASEDIR)/drivers/built_in.o
+ALL_OBJS-y               += $(BASEDIR)/xsm/built_in.o
 ALL_OBJS-$(ACM_SECURITY) += $(BASEDIR)/acm/built_in.o
 ALL_OBJS-y               += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
 
 CFLAGS-y                += -g -D__XEN__
+CFLAGS-$(XSM_ENABLE)    += -DXSM_ENABLE
 CFLAGS-$(ACM_SECURITY)  += -DACM_SECURITY
 CFLAGS-$(verbose)       += -DVERBOSE
 CFLAGS-$(crash_debug)   += -DCRASH_DEBUG
index a42efee417d8f36d764f043c60ae763a2660e013..40871491ae84534e00703234990226c99a5da096 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/hvm/hvm.h>
 #include <asm/hvm/support.h>
 #include <asm/processor.h>
+#include <xsm/xsm.h>
 
 long arch_do_domctl(
     struct xen_domctl *domctl,
@@ -64,6 +65,14 @@ long arch_do_domctl(
         if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
             break;
 
+        ret = xsm_ioport_permission(d, fp, 
+                                    domctl->u.ioport_permission.allow_access);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         if ( np == 0 )
             ret = 0;
         else if ( domctl->u.ioport_permission.allow_access )
@@ -90,6 +99,13 @@ long arch_do_domctl(
 
         page = mfn_to_page(mfn);
 
+        ret = xsm_getpageframeinfo(page);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         if ( likely(get_page(page, d)) )
         {
             ret = 0;
@@ -173,6 +189,10 @@ long arch_do_domctl(
 
                 page = mfn_to_page(mfn);
 
+                ret = xsm_getpageframeinfo(page);
+                if ( ret )
+                    continue;
+
                 if ( likely(mfn_valid(mfn) && get_page(page, d)) ) 
                 {
                     unsigned long type = 0;
@@ -230,6 +250,13 @@ long arch_do_domctl(
         ret = -EINVAL;
         if ( d != NULL )
         {
+            ret = xsm_getmemlist(d);
+            if ( ret )
+            {
+                rcu_unlock_domain(d);
+                break;
+            }
+
             ret = 0;
 
             spin_lock(&d->page_alloc_lock);
@@ -269,6 +296,13 @@ long arch_do_domctl(
         if ( unlikely(d == NULL) )
             break;
 
+        ret = xsm_hypercall_init(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         mfn = gmfn_to_mfn(d, gmfn);
 
         ret = -EACCES;
@@ -304,6 +338,10 @@ long arch_do_domctl(
         if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
             break;
 
+        ret = xsm_hvmcontext(d, domctl->cmd);
+        if ( ret )
+            goto sethvmcontext_out;
+
         ret = -EINVAL;
         if ( !is_hvm_domain(d) ) 
             goto sethvmcontext_out;
@@ -337,6 +375,10 @@ long arch_do_domctl(
         if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
             break;
 
+        ret = xsm_hvmcontext(d, domctl->cmd);
+        if ( ret )
+            goto gethvmcontext_out;
+
         ret = -EINVAL;
         if ( !is_hvm_domain(d) ) 
             goto gethvmcontext_out;
@@ -390,6 +432,13 @@ long arch_do_domctl(
         if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
             break;
 
+        ret = xsm_address_size(d, domctl->cmd);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         switch ( domctl->u.address_size.size )
         {
 #ifdef CONFIG_COMPAT
@@ -417,6 +466,13 @@ long arch_do_domctl(
         if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
             break;
 
+        ret = xsm_address_size(d, domctl->cmd);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         domctl->u.address_size.size = BITS_PER_GUEST_LONG(d);
 
         ret = 0;
index 91b5640e541f36b1721c6d377a11feb7539b49a8..fa9752cd78361eb42200445aca402ed1579b63ed 100644 (file)
@@ -1069,6 +1069,10 @@ static int hvmop_set_pci_intx_level(
     if ( !is_hvm_domain(d) )
         goto out;
 
+    rc = xsm_hvm_set_pci_intx_level(d);
+    if ( rc )
+        goto out;
+
     rc = 0;
     switch ( op.level )
     {
@@ -1112,6 +1116,10 @@ static int hvmop_set_isa_irq_level(
     if ( !is_hvm_domain(d) )
         goto out;
 
+    rc = xsm_hvm_set_isa_irq_level(d);
+    if ( rc )
+        goto out;
+
     rc = 0;
     switch ( op.level )
     {
@@ -1155,6 +1163,10 @@ static int hvmop_set_pci_link_route(
     if ( !is_hvm_domain(d) )
         goto out;
 
+    rc = xsm_hvm_set_pci_link_route(d);
+    if ( rc )
+        goto out;
+
     rc = 0;
     hvm_set_pci_link_route(d, op.link, op.isa_irq);
 
@@ -1204,6 +1216,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
         if ( !is_hvm_domain(d) )
             goto param_fail;
 
+        rc = xsm_hvm_param(d, op);
+        if ( rc )
+            goto param_fail;
+
         if ( op == HVMOP_set_param )
         {
             switch ( a.index )
index 5ff93f4d341dde997873345bd471442d6a1cb4b2..53c01dc1b4a8e788138c0e2942245cf0ccf574b4 100644 (file)
 #include <asm/hypercall.h>
 #include <asm/shared.h>
 #include <public/memory.h>
+#include <xsm/xsm.h>
 
 #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
 
@@ -2048,6 +2049,10 @@ int do_mmuext_op(
             type = PGT_l4_page_table;
 
         pin_page:
+            rc = xsm_memory_pin_page(current->domain, page);
+            if ( rc )
+                break;
+
             /* Ignore pinning of invalid paging levels. */
             if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) )
                 break;
@@ -2334,6 +2339,10 @@ int do_mmu_update(
              */
         case MMU_NORMAL_PT_UPDATE:
 
+            rc = xsm_mmu_normal_update(current->domain, req.val);
+            if ( rc )
+                break;
+
             gmfn = req.ptr >> PAGE_SHIFT;
             mfn = gmfn_to_mfn(d, gmfn);
 
@@ -2424,6 +2433,10 @@ int do_mmu_update(
             mfn = req.ptr >> PAGE_SHIFT;
             gpfn = req.val;
 
+            rc = xsm_mmu_machphys_update(current->domain, mfn);
+            if ( rc )
+                break;
+
             if ( unlikely(!get_page_from_pagenr(mfn, FOREIGNDOM)) )
             {
                 MEM_LOG("Could not get page for mach->phys update");
@@ -2802,6 +2815,10 @@ int do_update_va_mapping(unsigned long va, u64 val64,
     if ( unlikely(!__addr_ok(va) && !paging_mode_external(d)) )
         return -EINVAL;
 
+    rc = xsm_update_va_mapping(current->domain, val);
+    if ( rc )
+        return rc;
+
     LOCK_BIGLOCK(d);
 
     pl1e = guest_map_l1e(v, va, &gl1mfn);
@@ -3063,6 +3080,12 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
         else if ( (d = rcu_lock_domain_by_id(xatp.domid)) == NULL )
             return -ESRCH;
 
+        if ( xsm_add_to_physmap(current->domain, d) )
+        {
+            rcu_unlock_domain(d);
+            return -EPERM;
+        }
+
         switch ( xatp.space )
         {
         case XENMAPSPACE_shared_info:
@@ -3139,6 +3162,13 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
         else if ( (d = rcu_lock_domain_by_id(fmap.domid)) == NULL )
             return -ESRCH;
 
+        rc = xsm_domain_memory_map(d);
+        if ( rc )
+        {
+            rcu_unlock_domain(d);
+            return rc;
+        }
+
         rc = copy_from_guest(d->arch.e820, fmap.map.buffer,
                              fmap.map.nr_entries) ? -EFAULT : 0;
         d->arch.nr_e820 = fmap.map.nr_entries;
@@ -3172,10 +3202,15 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
         struct xen_memory_map memmap;
         XEN_GUEST_HANDLE(e820entry_t) buffer;
         int count;
+        int rc;
 
         if ( !IS_PRIV(current->domain) )
             return -EINVAL;
 
+        rc = xsm_machine_memory_map();
+        if ( rc )
+            return rc;
+
         if ( copy_from_guest(&memmap, arg, 1) )
             return -EFAULT;
         if ( memmap.nr_entries < e820.nr_map + 1 )
index ac4db900a53a8acda7781794b90f4bc610e29677..25f323151d4fb84c2a939c241184a5dc59e25f43 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/p2m.h>
 #include <asm/hap.h>
 #include <asm/guest_access.h>
+#include <xsm/xsm.h>
 
 /* Xen command-line option to enable hardware-assisted paging */
 int opt_hap_enabled;
@@ -402,6 +403,10 @@ int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
         return -EINVAL;
     }
 
+    rc = xsm_shadow_control(d, sc->op);
+    if ( rc )
+        return rc;
+
     /* Code to handle log-dirty. Note that some log dirty operations
      * piggy-back on shadow operations. For example, when
      * XEN_DOMCTL_SHADOW_OP_OFF is called, it first checks whether log dirty
index 7b9bfedb514ab0d63c3ab000fc8196174b12cdd7..78ff6b0ca860517de7e57d303761fac7ff48f732 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/hypercall.h>
 #include <public/xen.h>
 #include <public/physdev.h>
+#include <xsm/xsm.h>
 
 #ifndef COMPAT
 typedef long ret_t;
@@ -73,6 +74,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         ret = -EPERM;
         if ( !IS_PRIV(v->domain) )
             break;
+        ret = xsm_apic(v->domain, cmd);
+        if ( ret )
+            break;
         ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
         if ( copy_to_guest(arg, &apic, 1) != 0 )
             ret = -EFAULT;
@@ -87,6 +91,9 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         ret = -EPERM;
         if ( !IS_PRIV(v->domain) )
             break;
+        ret = xsm_apic(v->domain, cmd);
+        if ( ret )
+            break;
         ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
         break;
     }
@@ -102,6 +109,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         if ( !IS_PRIV(v->domain) )
             break;
 
+        ret = xsm_assign_vector(v->domain, irq_op.irq);
+        if ( ret )
+            break;
+
         irq = irq_op.irq;
         ret = -EINVAL;
         if ( (irq < 0) || (irq >= NR_IRQS) )
index 6d1f019343aa0cff55a65be5da99fc62eeeff63d..6228ea96711c38cb279b3240eaec012aad690512 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/edd.h>
 #include <asm/mtrr.h>
 #include "cpu/mtrr/mtrr.h"
+#include <xsm/xsm.h>
 
 extern uint16_t boot_edid_caps;
 extern uint8_t boot_edid_info[];
@@ -59,6 +60,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
     {
     case XENPF_settime:
     {
+        ret = xsm_xen_settime();
+        if ( ret )
+            break;
+
         do_settime(op->u.settime.secs, 
                    op->u.settime.nsecs, 
                    op->u.settime.system_time);
@@ -68,6 +73,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
 
     case XENPF_add_memtype:
     {
+        ret = xsm_memtype(op->cmd);
+        if ( ret )
+            break;
+
         ret = mtrr_add_page(
             op->u.add_memtype.mfn,
             op->u.add_memtype.nr_mfns,
@@ -86,6 +95,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
 
     case XENPF_del_memtype:
     {
+        ret = xsm_memtype(op->cmd);
+        if ( ret )
+            break;
+
         if (op->u.del_memtype.handle == 0
             /* mtrr/main.c otherwise does a lookup */
             && (int)op->u.del_memtype.reg >= 0)
@@ -105,6 +118,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
         unsigned int  nr_mfns;
         mtrr_type     type;
 
+        ret = xsm_memtype(op->cmd);
+        if ( ret )
+            break;
+
         ret = -EINVAL;
         if ( op->u.read_memtype.reg < num_var_ranges )
         {
@@ -120,6 +137,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
     case XENPF_microcode_update:
     {
         extern int microcode_update(XEN_GUEST_HANDLE(void), unsigned long len);
+
+        ret = xsm_microcode();
+        if ( ret )
+            break;
+
 #ifndef COMPAT
         ret = microcode_update(op->u.microcode.data,
                                op->u.microcode.length);
@@ -136,6 +158,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op)
     {
         extern int opt_noirqbalance;
         int quirk_id = op->u.platform_quirk.quirk_id;
+
+        ret = xsm_platform_quirk(quirk_id);
+        if ( ret )
+            break;
+
         switch ( quirk_id )
         {
         case QUIRK_NOIRQBALANCING:
index 31d669a2078b0c74df34fdd8b94659cbe58c8c87..fcc5073fce3d332aa650e2b2a7ca204ab3c70744 100644 (file)
@@ -35,6 +35,7 @@
 #include <acm/acm_hooks.h>
 #include <xen/kexec.h>
 #include <asm/edd.h>
+#include <xsm/xsm.h>
 
 #if defined(CONFIG_X86_64)
 #define BOOTSTRAP_DIRECTMAP_END (1UL << 32) /* 4GB */
@@ -963,6 +964,8 @@ void __init __start_xen(unsigned long mbi_p)
 
     percpu_init_areas();
 
+    xsm_init(&initrdidx, mbi, initial_images_start);
+
     init_idle_domain();
 
     trap_init();
index ff7018a930d13a41791ea76fff87de42bb7206aa..e518d4ce49484e988305ea8b097e69665c535c69 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/processor.h>
 #include <asm/numa.h>
 #include <xen/nodemask.h>
+#include <xsm/xsm.h>
 
 #define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
 
@@ -42,6 +43,10 @@ long arch_do_sysctl(
 
         xen_sysctl_physinfo_t *pi = &sysctl->u.physinfo;
 
+        ret = xsm_physinfo();
+        if ( ret )
+            break;
+
         pi->threads_per_core =
             cpus_weight(cpu_sibling_map[0]);
         pi->cores_per_socket =
index 8ca596e15fb25c1dc450bfc1ad87cbf28d1b1a15..6f243b8d1b1bf805a8b41c58c4cdce45dca25e9f 100644 (file)
@@ -676,6 +676,7 @@ ENTRY(hypercall_table)
         .long do_sysctl             /* 35 */
         .long do_domctl
         .long do_kexec_op
+        .long do_xsm_op
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long do_ni_hypercall
         .endr
@@ -719,6 +720,7 @@ ENTRY(hypercall_args_table)
         .byte 1 /* do_sysctl            */  /* 35 */
         .byte 1 /* do_domctl            */
         .byte 2 /* do_kexec_op          */
+        .byte 1 /* do_xsm_op            */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index d59cff95c4f2d579cef9bd0d9fd2f989e0930a35..08649f931ba385e4d48ca339be02730efa2016e9 100644 (file)
@@ -63,6 +63,8 @@ SECTIONS
   __initcall_start = .;
   .initcall.init : { *(.initcall1.init) } :text
   __initcall_end = .;
+   .xsm_initcall.init : { __xsm_initcall_start = .; 
+   *(.xsm_initcall.init) __xsm_initcall_end = .; }
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
index 0bef33070edc922f3017e8a4500311449f20cebb..69f27253045d92c62e3bdbf82812b97c1170edaa 100644 (file)
@@ -612,6 +612,7 @@ ENTRY(hypercall_table)
         .quad do_sysctl             /* 35 */
         .quad do_domctl
         .quad do_kexec_op
+        .quad do_xsm_op
         .rept NR_hypercalls-((.-hypercall_table)/8)
         .quad do_ni_hypercall
         .endr
@@ -655,6 +656,7 @@ ENTRY(hypercall_args_table)
         .byte 1 /* do_sysctl            */  /* 35 */
         .byte 1 /* do_domctl            */
         .byte 2 /* do_kexec             */
+        .byte 1 /* do_xsm_op            */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 1a8937f1e1c9e3ff47ad91faa8988428a3f141f3..b7f68a236fe6a55f0896062ba4ae30b238a1747d 100644 (file)
@@ -29,6 +29,7 @@
 #include <public/sched.h>
 #include <public/vcpu.h>
 #include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
 
 /* Protect updates/reads (resp.) of domain_list and domain_hash. */
 DEFINE_SPINLOCK(domlist_update_lock);
@@ -57,6 +58,13 @@ struct domain *alloc_domain(domid_t domid)
 
     memset(d, 0, sizeof(*d));
     d->domain_id = domid;
+
+    if ( xsm_alloc_security_domain(d) != 0 )
+    {
+        free_domain(d);
+        return NULL;
+    }
+
     atomic_set(&d->refcnt, 1);
     spin_lock_init(&d->big_lock);
     spin_lock_init(&d->page_alloc_lock);
@@ -69,6 +77,7 @@ struct domain *alloc_domain(domid_t domid)
 
 void free_domain(struct domain *d)
 {
+    xsm_free_security_domain(d);
     xfree(d);
 }
 
@@ -193,6 +202,9 @@ struct domain *domain_create(
 
     if ( !is_idle_domain(d) )
     {
+        if ( xsm_domain_create(d, ssidref) != 0 )
+            goto fail;
+
         d->is_paused_by_controller = 1;
         atomic_inc(&d->pause_count);
 
index 5d29667b7c3d0842719727c3b2316c002ac53406..c1c391e82d015d38e558fc8ad488a014c211f867 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/current.h>
 #include <public/domctl.h>
 #include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
 
 extern long arch_do_domctl(
     struct xen_domctl *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl);
@@ -127,7 +128,9 @@ void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info)
         info->ssidref = ((struct acm_ssid_domain *)d->ssid)->ssidref;
     else    
         info->ssidref = ACM_DEFAULT_SSID;
-    
+
+    xsm_security_domaininfo(d, info);
+
     info->tot_pages         = d->tot_pages;
     info->max_pages         = d->max_pages;
     info->shared_info_frame = mfn_to_gmfn(d, __pa(d->shared_info)>>PAGE_SHIFT);
@@ -204,6 +207,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_setvcpucontext(d);
+        if ( ret )
+            goto svc_out;
+
         ret = -EINVAL;
         if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) )
             goto svc_out;
@@ -251,12 +258,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         ret = -ESRCH;
         if ( d != NULL )
         {
+            ret = xsm_pausedomain(d);
+            if ( ret )
+                goto pausedomain_out;
+
             ret = -EINVAL;
             if ( d != current->domain )
             {
                 domain_pause_by_systemcontroller(d);
                 ret = 0;
             }
+        pausedomain_out:
             rcu_unlock_domain(d);
         }
     }
@@ -270,6 +282,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_unpausedomain(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         domain_unpause_by_systemcontroller(d);
         rcu_unlock_domain(d);
         ret = 0;
@@ -284,6 +303,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_resumedomain(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         domain_resume(d);
         rcu_unlock_domain(d);
         ret = 0;
@@ -359,6 +385,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = xsm_max_vcpus(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         /* Needed, for example, to ensure writable p.t. state is synced. */
         domain_pause(d);
 
@@ -395,12 +428,18 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         ret = -ESRCH;
         if ( d != NULL )
         {
+            ret = xsm_destroydomain(d);
+            if ( ret )
+                goto destroydomain_out;
+
             ret = -EINVAL;
             if ( d != current->domain )
             {
                 domain_kill(d);
                 ret = 0;
             }
+
+        destroydomain_out:
             rcu_unlock_domain(d);
         }
     }
@@ -418,6 +457,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_vcpuaffinity(op->cmd, d);
+        if ( ret )
+            goto vcpuaffinity_out;
+
         ret = -EINVAL;
         if ( op->u.vcpuaffinity.vcpu >= MAX_VIRT_CPUS )
             goto vcpuaffinity_out;
@@ -452,10 +495,15 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = xsm_scheduler(d);
+        if ( ret )
+            goto scheduler_op_out;
+
         ret = sched_adjust(d, &op->u.scheduler_op);
         if ( copy_to_guest(u_domctl, op, 1) )
             ret = -EFAULT;
 
+    scheduler_op_out:
         rcu_unlock_domain(d);
     }
     break;
@@ -478,12 +526,17 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
             break;
         }
 
+        ret = xsm_getdomaininfo(d);
+        if ( ret )
+            goto getdomaininfo_out;
+
         getdomaininfo(d, &op->u.getdomaininfo);
 
         op->domain = op->u.getdomaininfo.domain;
         if ( copy_to_guest(u_domctl, op, 1) )
             ret = -EFAULT;
 
+    getdomaininfo_out:
         rcu_read_unlock(&domlist_read_lock);
     }
     break;
@@ -498,6 +551,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = xsm_getvcpucontext(d);
+        if ( ret )
+            goto getvcpucontext_out;
+
         ret = -EINVAL;
         if ( op->u.vcpucontext.vcpu >= MAX_VIRT_CPUS )
             goto getvcpucontext_out;
@@ -554,6 +611,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
             break;
 
+        ret = xsm_getvcpuinfo(d);
+        if ( ret )
+            goto getvcpuinfo_out;
+
         ret = -EINVAL;
         if ( op->u.getvcpuinfo.vcpu >= MAX_VIRT_CPUS )
             goto getvcpuinfo_out;
@@ -589,6 +650,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_setdomainmaxmem(d);
+        if ( ret )
+            goto max_mem_out;
+
         ret = -EINVAL;
         new_max = op->u.max_mem.max_memkb >> (PAGE_SHIFT-10);
 
@@ -603,6 +668,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         }
         spin_unlock(&d->page_alloc_lock);
 
+    max_mem_out:
         rcu_unlock_domain(d);
     }
     break;
@@ -616,6 +682,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_setdomainhandle(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         memcpy(d->handle, op->u.setdomainhandle.handle,
                sizeof(xen_domain_handle_t));
         rcu_unlock_domain(d);
@@ -632,6 +705,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_setdebugging(d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            break;
+        }
+
         domain_pause(d);
         d->debugger_attached = !!op->u.setdebugging.enable;
         domain_unpause(d); /* causes guest to latch new status */
@@ -654,11 +734,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
+        if ( ret )
+            goto irq_permission_out;
+        
         if ( op->u.irq_permission.allow_access )
             ret = irq_permit_access(d, pirq);
         else
             ret = irq_deny_access(d, pirq);
 
+    irq_permission_out:
         rcu_unlock_domain(d);
     }
     break;
@@ -678,11 +763,16 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         if ( d == NULL )
             break;
 
+        ret = xsm_iomem_permission(d, mfn, op->u.iomem_permission.allow_access);
+        if ( ret )
+            goto iomem_permission_out;
+
         if ( op->u.iomem_permission.allow_access )
             ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
         else
             ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
 
+    iomem_permission_out:
         rcu_unlock_domain(d);
     }
     break;
@@ -695,6 +785,13 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
         d = rcu_lock_domain_by_id(op->domain);
         if ( d != NULL )
         {
+            ret = xsm_domain_settime(d);
+            if ( ret )
+            {
+                rcu_unlock_domain(d);
+                break;
+            }
+
             d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
             rcu_unlock_domain(d);
             ret = 0;
index 09533a0e14d6bf2091941b38edf7aabcc4291e98..145a238ccfc46e9f4efecf4fd64e5f32699db3d6 100644 (file)
@@ -30,6 +30,7 @@
 #include <public/xen.h>
 #include <public/event_channel.h>
 #include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
 
 #define bucket_from_port(d,p) \
     ((d)->evtchn[(p)/EVTCHNS_PER_BUCKET])
@@ -78,6 +79,7 @@ static int get_free_port(struct domain *d)
 {
     struct evtchn *chn;
     int            port;
+    int            i, j;
 
     if ( d->is_dying )
         return -EINVAL;
@@ -95,6 +97,19 @@ static int get_free_port(struct domain *d)
     memset(chn, 0, EVTCHNS_PER_BUCKET * sizeof(*chn));
     bucket_from_port(d, port) = chn;
 
+    for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
+    {
+        if ( xsm_alloc_security_evtchn(&chn[i]) )
+        {
+            for ( j = 0; j < i; j++ )
+            {
+                xsm_free_security_evtchn(&chn[j]);
+            }        
+            xfree(chn);
+            return -ENOMEM;
+        }
+    }
+
     return port;
 }
 
@@ -124,6 +139,10 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
         ERROR_EXIT(port);
     chn = evtchn_from_port(d, port);
 
+    rc = xsm_evtchn_unbound(d, chn, alloc->remote_dom);
+    if ( rc )
+        goto out;
+
     chn->state = ECS_UNBOUND;
     if ( (chn->u.unbound.remote_domid = alloc->remote_dom) == DOMID_SELF )
         chn->u.unbound.remote_domid = current->domain->domain_id;
@@ -180,6 +199,10 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
          (rchn->u.unbound.remote_domid != ld->domain_id) )
         ERROR_EXIT(-EINVAL);
 
+    rc = xsm_evtchn_interdomain(ld, lchn, rd, rchn);
+    if ( rc )
+        goto out;
+
     lchn->u.interdomain.remote_dom  = rd;
     lchn->u.interdomain.remote_port = (u16)rport;
     lchn->state                     = ECS_INTERDOMAIN;
@@ -422,6 +445,8 @@ static long __evtchn_close(struct domain *d1, int port1)
     chn1->state          = ECS_FREE;
     chn1->notify_vcpu_id = 0;
 
+    xsm_evtchn_close_post(chn1);
+
  out:
     if ( d2 != NULL )
     {
@@ -466,6 +491,10 @@ long evtchn_send(unsigned int lport)
         return -EINVAL;
     }
 
+    ret = xsm_evtchn_send(ld, lchn);
+    if ( ret )
+        goto out;
+
     switch ( lchn->state )
     {
     case ECS_INTERDOMAIN:
@@ -495,6 +524,7 @@ long evtchn_send(unsigned int lport)
         ret = -EINVAL;
     }
 
+out:
     spin_unlock(&ld->evtchn_lock);
 
     return ret;
@@ -613,6 +643,11 @@ static long evtchn_status(evtchn_status_t *status)
     }
 
     chn = evtchn_from_port(d, port);
+
+    rc = xsm_evtchn_status(d, chn);
+    if ( rc )
+        goto out;
+
     switch ( chn->state )
     {
     case ECS_FREE:
@@ -743,6 +778,7 @@ static long evtchn_reset(evtchn_reset_t *r)
     domid_t dom = r->dom;
     struct domain *d;
     int i;
+    int rc;
 
     if ( dom == DOMID_SELF )
         dom = current->domain->domain_id;
@@ -752,6 +788,13 @@ static long evtchn_reset(evtchn_reset_t *r)
     if ( (d = rcu_lock_domain_by_id(dom)) == NULL )
         return -ESRCH;
 
+    rc = xsm_evtchn_reset(current->domain, d);
+    if ( rc )
+    {
+        rcu_unlock_domain(d);
+        return rc;
+    }
+
     for ( i = 0; port_is_valid(d, i); i++ )
         (void)__evtchn_close(d, i);
 
@@ -969,7 +1012,10 @@ void evtchn_destroy(struct domain *d)
     /* Free all event-channel buckets. */
     spin_lock(&d->evtchn_lock);
     for ( i = 0; i < NR_EVTCHN_BUCKETS; i++ )
+    {
+        xsm_free_security_evtchn(d->evtchn[i]);
         xfree(d->evtchn[i]);
+    }
     spin_unlock(&d->evtchn_lock);
 }
 
index 8df6fb1cc167d6fdef3a0ea2cdde7d0494369295..e240452f149505b07696caeb20e857706178ef9b 100644 (file)
@@ -33,6 +33,7 @@
 #include <xen/guest_access.h>
 #include <xen/domain_page.h>
 #include <acm/acm_hooks.h>
+#include <xsm/xsm.h>
 
 #ifndef max_nr_grant_frames
 unsigned int max_nr_grant_frames = DEFAULT_MAX_NR_GRANT_FRAMES;
@@ -224,6 +225,14 @@ __gnttab_map_grant_ref(
         return;
     }
 
+    rc = xsm_grant_mapref(ld, rd, op->flags);
+    if ( rc )
+    {
+        rcu_unlock_domain(rd);
+        op->status = GNTST_permission_denied;
+        return;
+    }
+
     if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
     {
         rcu_unlock_domain(rd);
@@ -451,6 +460,14 @@ __gnttab_unmap_common(
         return;
     }
 
+    rc = xsm_grant_unmapref(ld, rd);
+    if ( rc )
+    {
+        rcu_unlock_domain(rd);
+        op->status = GNTST_permission_denied;
+        return;
+    }
+
     TRACE_1D(TRC_MEM_PAGE_GRANT_UNMAP, dom);
 
     spin_lock(&rd->grant_table->lock);
@@ -705,6 +722,13 @@ gnttab_setup_table(
         goto out;
     }
 
+    if ( xsm_grant_setup(current->domain, d) )
+    {
+        rcu_unlock_domain(d);
+        op.status = GNTST_permission_denied;
+        goto out;
+    }
+
     spin_lock(&d->grant_table->lock);
 
     if ( (op.nr_frames > nr_grant_frames(d->grant_table)) &&
@@ -745,6 +769,7 @@ gnttab_query_size(
     struct gnttab_query_size op;
     struct domain *d;
     domid_t        dom;
+    int rc;
 
     if ( count != 1 )
         return -EINVAL;
@@ -773,6 +798,14 @@ gnttab_query_size(
         goto query_out;
     }
 
+    rc = xsm_grant_query_size(current->domain, d);
+    if ( rc )
+    {
+        rcu_unlock_domain(d);
+        op.status = GNTST_permission_denied;
+        goto query_out;
+    }
+
     spin_lock(&d->grant_table->lock);
 
     op.nr_frames     = nr_grant_frames(d->grant_table);
@@ -919,6 +952,13 @@ gnttab_transfer(
             goto copyback;
         }
 
+        if ( xsm_grant_transfer(d, e) )
+        {
+            rcu_unlock_domain(e);
+            gop.status = GNTST_permission_denied;
+            goto copyback;
+        }
+
         spin_lock(&e->page_alloc_lock);
 
         /*
@@ -1139,6 +1179,13 @@ __gnttab_copy(
         PIN_FAIL(error_out, GNTST_bad_domain,
                  "couldn't find %d\n", op->dest.domid);
 
+    rc = xsm_grant_copy(sd, dd);
+    if ( rc )
+    {
+        rc = GNTST_permission_denied;
+        goto error_out;
+    }
+
     if ( src_is_gref )
     {
         rc = __acquire_grant_for_copy(sd, op->source.u.ref, 1, &s_frame);
index 2437799d636cc51744dc2cbe53a172de906313e9..4e95cf319d444a4a9e5b7f9d3d5e71afa4703c5a 100644 (file)
@@ -21,6 +21,7 @@
 #include <xen/version.h>
 #include <xen/console.h>
 #include <public/elfnote.h>
+#include <xsm/xsm.h>
 
 #ifndef COMPAT
 
@@ -367,6 +368,10 @@ ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
     if ( !IS_PRIV(current->domain) )
         return -EPERM;
 
+    ret = xsm_kexec();
+    if ( ret )
+        return ret;
+
     switch ( op )
     {
     case KEXEC_CMD_kexec_get_range:
index 311c5ae12341e4f768725f58d182fe335510ef04..783de29749fb689d41b028d0dff1c998cef512e6 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <public/memory.h>
+#include <xsm/xsm.h>
 
 struct memop_args {
     /* INPUT */
@@ -216,6 +217,7 @@ static long translate_gpfn_list(
     xen_pfn_t gpfn;
     xen_pfn_t mfn;
     struct domain *d;
+    int rc;
 
     if ( copy_from_guest(&op, uop, 1) )
         return -EFAULT;
@@ -259,6 +261,13 @@ static long translate_gpfn_list(
 
         mfn = gmfn_to_mfn(d, gpfn);
 
+        rc = xsm_translate_gpfn_list(current->domain, mfn);
+        if ( rc )
+        {
+            rcu_unlock_domain(d);
+            return rc;
+        }
+
         if ( unlikely(__copy_to_guest_offset(op.mfn_list, i, &mfn, 1)) )
         {
             rcu_unlock_domain(d);
@@ -538,6 +547,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
             return start_extent;
         args.domain = d;
 
+        rc = xsm_memory_adjust_reservation(current->domain, d);
+        if ( rc )
+        {
+            if ( reservation.domid != DOMID_SELF )
+                rcu_unlock_domain(d);
+            return rc;
+        }
+
         switch ( op )
         {
         case XENMEM_increase_reservation:
@@ -584,6 +601,14 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg)
         else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
             return -ESRCH;
 
+        rc = xsm_memory_stat_reservation(current->domain, d);
+        if ( rc )
+        {
+            if ( domid != DOMID_SELF )
+                rcu_unlock_domain(d);
+            return rc;
+        }
+
         switch ( op )
         {
         case XENMEM_current_reservation:
index 7911f5f99c342cb94cd985cef44bd5485b92add7..50aacafb619bca48d517badf6a2b8d120b40d97f 100644 (file)
@@ -32,6 +32,7 @@
 #include <xen/guest_access.h>
 #include <xen/multicall.h>
 #include <public/sched.h>
+#include <xsm/xsm.h>
 
 /* opt_sched: scheduler - default to credit */
 static char opt_sched[10] = "credit";
@@ -461,6 +462,13 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg)
         if ( d == NULL )
             break;
 
+        ret = xsm_schedop_shutdown(current->domain, d);
+        if ( ret )
+        {
+            rcu_unlock_domain(d);
+            return ret;
+        }
+
         /* domain_pause() prevens any further execution in guest context. */
         domain_pause(d);
         domain_shutdown(d, (u8)sched_remote_shutdown.reason);
index 98d3777e0a4a27ca1a628db2b92299c22f05f10b..39d0d8c31dd8d3ac38d92e70140ed8ec2576a8b9 100644 (file)
@@ -23,6 +23,7 @@
 #include <public/sysctl.h>
 #include <asm/numa.h>
 #include <xen/nodemask.h>
+#include <xsm/xsm.h>
 
 extern long arch_do_sysctl(
     struct xen_sysctl *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl);
@@ -48,6 +49,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
     {
     case XEN_SYSCTL_readconsole:
     {
+        ret = xsm_readconsole(op->u.readconsole.clear);
+        if ( ret )
+            break;
+
         ret = read_console_ring(
             guest_handle_cast(op->u.readconsole.buffer, char),
             &op->u.readconsole.count,
@@ -59,6 +64,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
 
     case XEN_SYSCTL_tbuf_op:
     {
+        ret = xsm_tbufcontrol();
+        if ( ret )
+            break;
+
         ret = tb_control(&op->u.tbuf_op);
         if ( copy_to_guest(u_sysctl, op, 1) )
             ret = -EFAULT;
@@ -67,6 +76,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
     
     case XEN_SYSCTL_sched_id:
     {
+        ret = xsm_sched_id();
+        if ( ret )
+            break;
+
         op->u.sched_id.sched_id = sched_id();
         if ( copy_to_guest(u_sysctl, op, 1) )
             ret = -EFAULT;
@@ -90,6 +103,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
             if ( num_domains == op->u.getdomaininfolist.max_domains )
                 break;
 
+            ret = xsm_getdomaininfo(d);
+            if ( ret )
+                continue;
+
             getdomaininfo(d, &info);
 
             if ( copy_to_guest_offset(op->u.getdomaininfolist.buffer,
@@ -117,6 +134,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
 #ifdef PERF_COUNTERS
     case XEN_SYSCTL_perfc_op:
     {
+        ret = xsm_perfcontrol();
+        if ( ret )
+            break;
+
         ret = perfc_control(&op->u.perfc_op);
         if ( copy_to_guest(u_sysctl, op, 1) )
             ret = -EFAULT;
index e25ad7bb30fdde1770067d25e074b2485bb7ae6b..fee2a6556b079a2f2efa3d9a8bc1e85e49bce3dd 100644 (file)
@@ -14,6 +14,7 @@
 #include <xen/sched.h>
 #include <public/xenoprof.h>
 #include <xen/paging.h>
+#include <xsm/xsm.h>
 
 /* Limit amount of pages used for shared buffer (per domain) */
 #define MAX_OPROF_SHARED_PAGES 32
@@ -634,6 +635,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
         return -EPERM;
     }
 
+    ret = xsm_profile(current->domain, op);
+    if ( ret )
+        return ret;
+
     spin_lock(&xenoprof_lock);
     
     switch ( op )
index de351265dba8a01638ab74fb3040a5bbd9349440..1d88fc80783e6cb0d820bbd6067e5ccd892fb4ed 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/debugger.h>
 #include <asm/io.h>
 #include <asm/div64.h>
+#include <xsm/xsm.h>
 
 /* console: comma-separated list of console outputs. */
 static char opt_console[30] = OPT_CONSOLE_STR;
@@ -358,6 +359,10 @@ long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
         return -EPERM;
 #endif
 
+    rc = xsm_console_io(current->domain, cmd);
+    if ( rc )
+        return rc;
+
     switch ( cmd )
     {
     case CONSOLEIO_write:
index e686ccb99c737e0fa221fdccf36ff68ca108e2fa..0017c3fa5dab53ee2da0264d30b7320739b0b97f 100644 (file)
@@ -80,6 +80,7 @@
 #define __HYPERVISOR_sysctl               35
 #define __HYPERVISOR_domctl               36
 #define __HYPERVISOR_kexec_op             37
+#define __HYPERVISOR_xsm_op               38
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
index 3ce04ded058b575bb6c1eb8da3c47cb387bc7dfe..3fc9b3ee4f60310449106f5ec218b45f2734febe 100644 (file)
@@ -15,6 +15,7 @@
 #include <public/acm_ops.h>
 #include <public/event_channel.h>
 #include <asm/hypercall.h>
+#include <xsm/xsm.h>
 
 extern long
 do_ni_hypercall(
@@ -125,4 +126,8 @@ compat_memory_op(
 
 #endif
 
+extern long
+do_xsm_op(
+    XEN_GUEST_HANDLE(xsm_op_t) u_xsm_op);
+
 #endif /* __XEN_HYPERCALL_H__ */
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
new file mode 100644 (file)
index 0000000..3a6cbde
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ *  This file contains the XSM hook definitions for Xen.
+ *
+ *  This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ */
+
+#ifndef __XSM_H__
+#define __XSM_H__
+
+#include <xen/sched.h>
+#include <xen/multiboot.h>
+
+typedef void xsm_op_t;
+DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
+
+extern long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op);
+
+#ifdef XSM_ENABLE
+    #define xsm_call(fn) xsm_ops->fn
+#else
+    #define xsm_call(fn) 0
+#endif
+
+/* policy magic number (defined by XSM_MAGIC) */
+typedef u32 xsm_magic_t;
+#ifndef XSM_MAGIC
+#define XSM_MAGIC 0x00000000
+#endif
+
+#ifdef XSM_ENABLE
+
+extern char *policy_buffer;
+extern u32 policy_size;
+
+typedef int (*xsm_initcall_t)(void);
+
+extern xsm_initcall_t __xsm_initcall_start[], __xsm_initcall_end[];
+
+#define xsm_initcall(fn) \
+    static xsm_initcall_t __initcall_##fn \
+    __attribute_used__ __attribute__((__section__(".xsm_initcall.init"))) = fn
+
+struct xsm_operations {
+    void (*security_domaininfo) (struct domain *d,
+                                        struct xen_domctl_getdomaininfo *info);
+    int (*setvcpucontext) (struct domain *d);
+    int (*pausedomain) (struct domain *d);
+    int (*unpausedomain) (struct domain *d);
+    int (*resumedomain) (struct domain *d);
+    int (*domain_create) (struct domain *d, u32 ssidref);
+    int (*max_vcpus) (struct domain *d);
+    int (*destroydomain) (struct domain *d);
+    int (*vcpuaffinity) (int cmd, struct domain *d);
+    int (*scheduler) (struct domain *d);
+    int (*getdomaininfo) (struct domain *d);
+    int (*getvcpucontext) (struct domain *d);
+    int (*getvcpuinfo) (struct domain *d);
+    int (*domain_settime) (struct domain *d);
+    int (*tbufcontrol) (void);
+    int (*readconsole) (uint32_t clear);
+    int (*sched_id) (void);
+    int (*setdomainmaxmem) (struct domain *d);
+    int (*setdomainhandle) (struct domain *d);
+    int (*setdebugging) (struct domain *d);
+    int (*irq_permission) (struct domain *d, uint8_t pirq, uint8_t access);
+    int (*iomem_permission) (struct domain *d, unsigned long mfn, 
+                                                                uint8_t access);
+    int (*perfcontrol) (void);
+
+    int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
+    int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
+                                        struct domain *d2, struct evtchn *chn2);
+    void (*evtchn_close_post) (struct evtchn *chn);
+    int (*evtchn_send) (struct domain *d, struct evtchn *chn);
+    int (*evtchn_status) (struct domain *d, struct evtchn *chn);
+    int (*evtchn_reset) (struct domain *d1, struct domain *d2);
+
+    int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags);
+    int (*grant_unmapref) (struct domain *d1, struct domain *d2);
+    int (*grant_setup) (struct domain *d1, struct domain *d2);
+    int (*grant_transfer) (struct domain *d1, struct domain *d2);
+    int (*grant_copy) (struct domain *d1, struct domain *d2);
+    int (*grant_query_size) (struct domain *d1, struct domain *d2);
+
+    int (*alloc_security_domain) (struct domain *d);
+    void (*free_security_domain) (struct domain *d);
+    int (*alloc_security_evtchn) (struct evtchn *chn);
+    void (*free_security_evtchn) (struct evtchn *chn);
+
+    int (*translate_gpfn_list) (struct domain *d, unsigned long mfn);
+    int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2);
+    int (*memory_stat_reservation) (struct domain *d1, struct domain *d2);
+    int (*memory_pin_page) (struct domain *d, struct page_info *page);
+    int (*update_va_mapping) (struct domain *d, l1_pgentry_t pte);
+
+    int (*console_io) (struct domain *d, int cmd);
+
+    int (*profile) (struct domain *d, int op);
+
+    int (*kexec) (void);
+    int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
+
+    long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op);
+    void (*complete_init) (struct domain *d);
+
+#ifdef CONFIG_X86
+    int (*shadow_control) (struct domain *d, uint32_t op);
+    int (*ioport_permission) (struct domain *d, uint32_t ioport, 
+                                                                uint8_t access);
+    int (*getpageframeinfo) (struct page_info *page);
+    int (*getmemlist) (struct domain *d);
+    int (*hypercall_init) (struct domain *d);
+    int (*hvmcontext) (struct domain *d, uint32_t op);
+    int (*address_size) (struct domain *d, uint32_t op);
+    int (*hvm_param) (struct domain *d, unsigned long op);
+    int (*hvm_set_pci_intx_level) (struct domain *d);
+    int (*hvm_set_isa_irq_level) (struct domain *d);
+    int (*hvm_set_pci_link_route) (struct domain *d);
+    int (*apic) (struct domain *d, int cmd);
+    int (*assign_vector) (struct domain *d, uint32_t pirq);
+    int (*xen_settime) (void);
+    int (*memtype) (uint32_t access);
+    int (*microcode) (void);
+    int (*physinfo) (void);
+    int (*platform_quirk) (uint32_t);
+    int (*machine_memory_map) (void);
+    int (*domain_memory_map) (struct domain *d);
+    int (*mmu_normal_update) (struct domain *d, intpte_t fpte);
+    int (*mmu_machphys_update) (struct domain *d, unsigned long mfn);
+    int (*add_to_physmap) (struct domain *d1, struct domain *d2);
+#endif
+};
+
+#endif
+
+extern struct xsm_operations *xsm_ops;
+
+static inline void xsm_security_domaininfo (struct domain *d,
+                                        struct xen_domctl_getdomaininfo *info)
+{
+    xsm_call(security_domaininfo(d, info));
+}
+
+static inline int xsm_setvcpucontext(struct domain *d)
+{
+    return xsm_call(setvcpucontext(d));
+}
+
+static inline int xsm_pausedomain (struct domain *d)
+{
+    return xsm_call(pausedomain(d));
+}
+
+static inline int xsm_unpausedomain (struct domain *d)
+{
+    return xsm_call(unpausedomain(d));
+}
+
+static inline int xsm_resumedomain (struct domain *d)
+{
+    return xsm_call(resumedomain(d));
+}
+
+static inline int xsm_domain_create (struct domain *d, u32 ssidref)
+{
+    return xsm_call(domain_create(d, ssidref));
+}
+
+static inline int xsm_max_vcpus(struct domain *d)
+{
+    return xsm_call(max_vcpus(d));
+}
+
+static inline int xsm_destroydomain (struct domain *d)
+{
+    return xsm_call(destroydomain(d));
+}
+
+static inline int xsm_vcpuaffinity (int cmd, struct domain *d)
+{
+    return xsm_call(vcpuaffinity(cmd, d));
+}
+
+static inline int xsm_scheduler (struct domain *d)
+{
+    return xsm_call(scheduler(d));
+}
+
+static inline int xsm_getdomaininfo (struct domain *d)
+{
+    return xsm_call(getdomaininfo(d));
+}
+
+static inline int xsm_getvcpucontext (struct domain *d)
+{
+    return xsm_call(getvcpucontext(d));
+}
+
+static inline int xsm_getvcpuinfo (struct domain *d)
+{
+    return xsm_call(getvcpuinfo(d));
+}
+
+static inline int xsm_domain_settime (struct domain *d)
+{
+    return xsm_call(domain_settime(d));
+}
+
+static inline int xsm_tbufcontrol (void)
+{
+    return xsm_call(tbufcontrol());
+}
+
+static inline int xsm_readconsole (uint32_t clear)
+{
+    return xsm_call(readconsole(clear));
+}
+
+static inline int xsm_sched_id (void)
+{
+    return xsm_call(sched_id());
+}
+
+static inline int xsm_setdomainmaxmem (struct domain *d)
+{
+    return xsm_call(setdomainmaxmem(d));
+}
+
+static inline int xsm_setdomainhandle (struct domain *d)
+{
+    return xsm_call(setdomainhandle(d));
+}
+
+static inline int xsm_setdebugging (struct domain *d)
+{
+    return xsm_call(setdebugging(d));
+}
+
+static inline int xsm_irq_permission (struct domain *d, uint8_t pirq,
+                                                                uint8_t access)
+{
+    return xsm_call(irq_permission(d, pirq, access));
+} 
+
+static inline int xsm_iomem_permission (struct domain *d, unsigned long mfn,
+                                                                uint8_t access)
+{
+    return xsm_call(iomem_permission(d, mfn, access));
+}
+
+static inline int xsm_perfcontrol (void)
+{
+    return xsm_call(perfcontrol());
+}
+
+static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn,
+                                                                    domid_t id2)
+{
+    return xsm_call(evtchn_unbound(d1, chn, id2));
+}
+
+static inline int xsm_evtchn_interdomain (struct domain *d1, 
+                struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
+{
+    return xsm_call(evtchn_interdomain(d1, chan1, d2, chan2));
+}
+
+static inline void xsm_evtchn_close_post (struct evtchn *chn)
+{
+    xsm_call(evtchn_close_post(chn));
+}
+
+static inline int xsm_evtchn_send (struct domain *d, struct evtchn *chn)
+{
+    return xsm_call(evtchn_send(d, chn));
+}
+
+static inline int xsm_evtchn_status (struct domain *d, struct evtchn *chn)
+{
+    return xsm_call(evtchn_status(d, chn));
+}
+
+static inline int xsm_evtchn_reset (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(evtchn_reset(d1, d2));
+}
+
+static inline int xsm_grant_mapref (struct domain *d1, struct domain *d2,
+                                                                uint32_t flags)
+{
+    return xsm_call(grant_mapref(d1, d2, flags));
+}
+
+static inline int xsm_grant_unmapref (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(grant_unmapref(d1, d2));
+}
+
+static inline int xsm_grant_setup (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(grant_setup(d1, d2));
+}
+
+static inline int xsm_grant_transfer (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(grant_transfer(d1, d2));
+}
+
+static inline int xsm_grant_copy (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(grant_copy(d1, d2));
+}
+
+static inline int xsm_grant_query_size (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(grant_query_size(d1, d2));
+}
+
+static inline int xsm_alloc_security_domain (struct domain *d)
+{
+    return xsm_call(alloc_security_domain(d));
+}
+
+static inline void xsm_free_security_domain (struct domain *d)
+{
+    xsm_call(free_security_domain(d));
+}
+
+static inline int xsm_alloc_security_evtchn (struct evtchn *chn)
+{
+    return xsm_call(alloc_security_evtchn(chn));
+}
+
+static inline void xsm_free_security_evtchn (struct evtchn *chn)
+{
+    xsm_call(free_security_evtchn(chn));
+}
+
+static inline int xsm_translate_gpfn_list (struct domain *d, unsigned long mfn)
+{
+    return xsm_call(translate_gpfn_list(d, mfn));
+}
+
+static inline int xsm_memory_adjust_reservation (struct domain *d1, struct
+                                                                    domain *d2)
+{
+    return xsm_call(memory_adjust_reservation(d1, d2));
+}
+
+static inline int xsm_memory_stat_reservation (struct domain *d1,
+                                                            struct domain *d2)
+{
+    return xsm_call(memory_stat_reservation(d1, d2));
+}
+
+static inline int xsm_memory_pin_page(struct domain *d, struct page_info *page)
+{
+    return xsm_call(memory_pin_page(d, page));
+}
+
+static inline int xsm_update_va_mapping(struct domain *d, l1_pgentry_t pte)
+{
+    return xsm_call(update_va_mapping(d, pte));
+}
+
+static inline int xsm_console_io (struct domain *d, int cmd)
+{
+    return xsm_call(console_io(d, cmd));
+}
+
+static inline int xsm_profile (struct domain *d, int op)
+{
+    return xsm_call(profile(d, op));
+}
+
+static inline int xsm_kexec (void)
+{
+    return xsm_call(kexec());
+}
+
+static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2)
+{
+    return xsm_call(schedop_shutdown(d1, d2));
+}
+
+static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+    return xsm_call(__do_xsm_op(op));
+}
+
+static inline void xsm_complete_init (struct domain *d)
+{
+    xsm_call(complete_init(d));
+}
+
+#ifdef XSM_ENABLE
+extern int xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+                                          unsigned long initial_images_start);
+extern int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+                                           unsigned long initial_images_start);
+extern int register_xsm(struct xsm_operations *ops);
+extern int unregister_xsm(struct xsm_operations *ops);
+#else
+static inline int xsm_init (unsigned int *initrdidx,
+                const multiboot_info_t *mbi, unsigned long initial_images_start)
+{
+    return 0;
+}
+#endif
+
+#ifdef CONFIG_X86
+static inline int xsm_shadow_control (struct domain *d, uint32_t op)
+{
+    return xsm_call(shadow_control(d, op));
+}
+
+static inline int xsm_ioport_permission (struct domain *d, uint32_t ioport,
+                                                                uint8_t access)
+{
+    return xsm_call(ioport_permission(d, ioport, access));
+}
+
+static inline int xsm_getpageframeinfo (struct page_info *page)
+{
+    return xsm_call(getpageframeinfo(page));
+}
+
+static inline int xsm_getmemlist (struct domain *d)
+{
+    return xsm_call(getmemlist(d));
+}
+
+static inline int xsm_hypercall_init (struct domain *d)
+{
+    return xsm_call(hypercall_init(d));
+}
+
+static inline int xsm_hvmcontext (struct domain *d, uint32_t cmd)
+{
+    return xsm_call(hvmcontext(d, cmd));
+}
+
+static inline int xsm_address_size (struct domain *d, uint32_t cmd)
+{
+    return xsm_call(address_size(d, cmd));
+}
+
+static inline int xsm_hvm_param (struct domain *d, unsigned long op)
+{
+    return xsm_call(hvm_param(d, op));
+}
+
+static inline int xsm_hvm_set_pci_intx_level (struct domain *d)
+{
+    return xsm_call(hvm_set_pci_intx_level(d));
+}
+
+static inline int xsm_hvm_set_isa_irq_level (struct domain *d)
+{
+    return xsm_call(hvm_set_isa_irq_level(d));
+}
+
+static inline int xsm_hvm_set_pci_link_route (struct domain *d)
+{
+    return xsm_call(hvm_set_pci_link_route(d));
+}
+
+static inline int xsm_apic (struct domain *d, int cmd)
+{
+    return xsm_call(apic(d, cmd));
+}
+
+static inline int xsm_assign_vector (struct domain *d, uint32_t pirq)
+{
+    return xsm_call(assign_vector(d, pirq));
+}
+
+static inline int xsm_xen_settime (void)
+{
+    return xsm_call(xen_settime());
+}
+
+static inline int xsm_memtype (uint32_t access)
+{
+    return xsm_call(memtype(access));
+}
+
+static inline int xsm_microcode (void)
+{
+    return xsm_call(microcode());
+}
+
+static inline int xsm_physinfo (void)
+{
+    return xsm_call(physinfo());
+}
+
+static inline int xsm_platform_quirk (uint32_t quirk)
+{
+    return xsm_call(platform_quirk(quirk));
+}
+
+static inline int xsm_machine_memory_map(void)
+{
+    return xsm_call(machine_memory_map());
+}
+
+static inline int xsm_domain_memory_map(struct domain *d)
+{
+    return xsm_call(domain_memory_map(d));
+}
+
+static inline int xsm_mmu_normal_update (struct domain *d, intpte_t fpte)
+{
+    return xsm_call(mmu_normal_update(d, fpte));
+}
+
+static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn)
+{
+    return xsm_call(mmu_machphys_update(d, mfn));
+}
+
+static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
+{
+    return xsm_call(add_to_physmap(d1, d2));
+}
+#endif /* CONFIG_X86 */
+
+#endif /* __XSM_H */
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
new file mode 100644 (file)
index 0000000..252459c
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y += xsm_core.o
+obj-y += xsm_policy.o
+ifeq ($(XSM_ENABLE),y)
+obj-y += dummy.o
+endif
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
new file mode 100644 (file)
index 0000000..c572f67
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ *  This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ */
+
+#include <xen/sched.h>
+#include <xsm/xsm.h>
+
+static void dummy_security_domaininfo(struct domain *d,
+                                    struct xen_domctl_getdomaininfo *info)
+{
+    return;
+}
+
+static int dummy_setvcpucontext(struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_pausedomain (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_unpausedomain (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_resumedomain (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_domain_create(struct domain *d, u32 ssidref)
+{
+    return 0;
+}
+
+static int dummy_max_vcpus(struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_destroydomain (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_vcpuaffinity (int cmd, struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_scheduler (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_getdomaininfo (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_getvcpucontext (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_getvcpuinfo (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_domain_settime (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_tbufcontrol (void)
+{
+    return 0;
+}
+
+static int dummy_readconsole (uint32_t clear)
+{
+    return 0;
+}
+
+static int dummy_sched_id (void)
+{
+    return 0;
+}
+
+static int dummy_setdomainmaxmem (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_setdomainhandle (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_setdebugging (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_irq_permission (struct domain *d, uint8_t pirq, uint8_t access)
+{
+    return 0;
+}
+
+static int dummy_iomem_permission (struct domain *d, unsigned long mfn,
+                                                                uint8_t access)
+{
+    return 0;
+}
+
+static int dummy_perfcontrol (void)
+{
+    return 0;
+}
+
+static int dummy_alloc_security_domain (struct domain *d)
+{
+    return 0;
+}
+
+static void dummy_free_security_domain (struct domain *d)
+{
+    return;
+}
+
+static int dummy_grant_mapref (struct domain *d1, struct domain *d2,
+                                                                uint32_t flags)
+{
+    return 0;
+}
+
+static int dummy_grant_unmapref (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_grant_setup (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_grant_transfer (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_grant_copy (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_grant_query_size (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_translate_gpfn_list (struct domain *d, unsigned long mfn)
+{
+    return 0;
+}
+
+static int dummy_memory_adjust_reservation (struct domain *d1,
+                                                            struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_memory_stat_reservation (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_update_va_mapping (struct domain *d, l1_pgentry_t pte)
+{
+    return 0;
+}
+
+static int dummy_console_io (struct domain *d, int cmd)
+{
+    return 0;
+}
+
+static int dummy_profile (struct domain *d, int op)
+{
+    return 0;
+}
+
+static int dummy_kexec (void)
+{
+    return 0;
+}
+
+static int dummy_schedop_shutdown (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_memory_pin_page(struct domain *d, struct page_info *page)
+{
+    return 0;
+}
+
+static int dummy_evtchn_unbound (struct domain *d, struct evtchn *chn,
+                                                                    domid_t id2)
+{
+    return 0;
+}
+
+static int dummy_evtchn_interdomain (struct domain *d1, struct evtchn
+                                *chan1, struct domain *d2, struct evtchn *chan2)
+{
+    return 0;
+}
+
+static void dummy_evtchn_close_post (struct evtchn *chn)
+{
+    return;
+}
+
+static int dummy_evtchn_send (struct domain *d, struct evtchn *chn)
+{
+    return 0;
+}
+
+static int dummy_evtchn_status (struct domain *d, struct evtchn *chn)
+{
+    return 0;
+}
+
+static int dummy_evtchn_reset (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+
+static int dummy_alloc_security_evtchn (struct evtchn *chn)
+{
+    return 0;
+}
+
+static void dummy_free_security_evtchn (struct evtchn *chn)
+{
+    return;
+}
+
+static void dummy_complete_init (struct domain *d)
+{
+    return;
+}
+
+static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+    return -ENOSYS;
+}
+
+#ifdef CONFIG_X86
+static int dummy_shadow_control (struct domain *d, uint32_t op)
+{
+    return 0;
+}
+
+static int dummy_ioport_permission (struct domain *d, uint32_t ioport, 
+                                                                uint8_t access)
+{
+    return 0;
+}
+
+static int dummy_getpageframeinfo (struct page_info *page)
+{
+    return 0;
+}
+
+static int dummy_getmemlist (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_hypercall_init (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_hvmcontext (struct domain *d, uint32_t cmd)
+{
+    return 0;
+}
+
+static int dummy_address_size (struct domain *d, uint32_t cmd)
+{
+    return 0;
+}
+
+static int dummy_hvm_param (struct domain *d, unsigned long op)
+{
+    return 0;
+}
+
+static int dummy_hvm_set_pci_intx_level (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_hvm_set_isa_irq_level (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_hvm_set_pci_link_route (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_apic (struct domain *d, int cmd)
+{
+    return 0;
+}
+
+static int dummy_assign_vector (struct domain *d, uint32_t pirq)
+{
+    return 0;
+}
+
+static int dummy_xen_settime (void)
+{
+    return 0;
+}
+
+static int dummy_memtype (uint32_t access)
+{
+    return 0;
+}
+
+static int dummy_microcode (void)
+{
+    return 0;
+}
+
+static int dummy_physinfo (void)
+{
+    return 0;
+}
+
+static int dummy_platform_quirk (uint32_t quirk)
+{
+    return 0;
+}
+
+static int dummy_machine_memory_map (void)
+{
+    return 0;
+}
+
+static int dummy_domain_memory_map (struct domain *d)
+{
+    return 0;
+}
+
+static int dummy_mmu_normal_update (struct domain *d, intpte_t fpte)
+{
+    return 0;
+}
+
+static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn)
+{
+    return 0;
+}
+
+static int dummy_add_to_physmap (struct domain *d1, struct domain *d2)
+{
+    return 0;
+}
+#endif
+
+struct xsm_operations dummy_xsm_ops;
+
+#define set_to_dummy_if_null(ops, function)                        \
+    do {                                                           \
+        if ( !ops->function )                                      \
+        {                                                          \
+            ops->function = dummy_##function;                      \
+            dprintk(XENLOG_DEBUG, "Had to override the " #function \
+                " security operation with the dummy one.\n");      \
+        }                                                          \
+    } while (0)
+
+void xsm_fixup_ops (struct xsm_operations *ops)
+{
+    set_to_dummy_if_null(ops, security_domaininfo);
+    set_to_dummy_if_null(ops, setvcpucontext);
+    set_to_dummy_if_null(ops, pausedomain);
+    set_to_dummy_if_null(ops, unpausedomain);
+    set_to_dummy_if_null(ops, resumedomain);
+    set_to_dummy_if_null(ops, domain_create);
+    set_to_dummy_if_null(ops, max_vcpus);
+    set_to_dummy_if_null(ops, destroydomain);
+    set_to_dummy_if_null(ops, vcpuaffinity);
+    set_to_dummy_if_null(ops, scheduler);
+    set_to_dummy_if_null(ops, getdomaininfo);
+    set_to_dummy_if_null(ops, getvcpucontext);
+    set_to_dummy_if_null(ops, getvcpuinfo);
+    set_to_dummy_if_null(ops, domain_settime);
+    set_to_dummy_if_null(ops, tbufcontrol);
+    set_to_dummy_if_null(ops, readconsole);
+    set_to_dummy_if_null(ops, sched_id);
+    set_to_dummy_if_null(ops, setdomainmaxmem);
+    set_to_dummy_if_null(ops, setdomainhandle);
+    set_to_dummy_if_null(ops, setdebugging);
+    set_to_dummy_if_null(ops, irq_permission);
+    set_to_dummy_if_null(ops, iomem_permission);
+    set_to_dummy_if_null(ops, perfcontrol);
+
+    set_to_dummy_if_null(ops, evtchn_unbound);
+    set_to_dummy_if_null(ops, evtchn_interdomain);
+    set_to_dummy_if_null(ops, evtchn_close_post);
+    set_to_dummy_if_null(ops, evtchn_send);
+    set_to_dummy_if_null(ops, evtchn_status);
+    set_to_dummy_if_null(ops, evtchn_reset);
+
+    set_to_dummy_if_null(ops, grant_mapref);
+    set_to_dummy_if_null(ops, grant_unmapref);
+    set_to_dummy_if_null(ops, grant_setup);
+    set_to_dummy_if_null(ops, grant_transfer);
+    set_to_dummy_if_null(ops, grant_copy);
+    set_to_dummy_if_null(ops, grant_query_size);
+
+    set_to_dummy_if_null(ops, alloc_security_domain);
+    set_to_dummy_if_null(ops, free_security_domain);
+    set_to_dummy_if_null(ops, alloc_security_evtchn);
+    set_to_dummy_if_null(ops, free_security_evtchn);
+
+    set_to_dummy_if_null(ops, translate_gpfn_list);
+    set_to_dummy_if_null(ops, memory_adjust_reservation);
+    set_to_dummy_if_null(ops, memory_stat_reservation);
+    set_to_dummy_if_null(ops, memory_pin_page);
+    set_to_dummy_if_null(ops, update_va_mapping);
+
+    set_to_dummy_if_null(ops, console_io);
+
+    set_to_dummy_if_null(ops, profile);
+
+    set_to_dummy_if_null(ops, kexec);
+    set_to_dummy_if_null(ops, schedop_shutdown);
+
+    set_to_dummy_if_null(ops, __do_xsm_op);
+    set_to_dummy_if_null(ops, complete_init);
+
+#ifdef CONFIG_X86
+    set_to_dummy_if_null(ops, shadow_control);
+    set_to_dummy_if_null(ops, ioport_permission);
+    set_to_dummy_if_null(ops, getpageframeinfo);
+    set_to_dummy_if_null(ops, getmemlist);
+    set_to_dummy_if_null(ops, hypercall_init);
+    set_to_dummy_if_null(ops, hvmcontext);
+    set_to_dummy_if_null(ops, address_size);
+    set_to_dummy_if_null(ops, hvm_param);
+    set_to_dummy_if_null(ops, hvm_set_pci_intx_level);
+    set_to_dummy_if_null(ops, hvm_set_isa_irq_level);
+    set_to_dummy_if_null(ops, hvm_set_pci_link_route);
+    set_to_dummy_if_null(ops, apic);
+    set_to_dummy_if_null(ops, assign_vector);
+    set_to_dummy_if_null(ops, xen_settime);
+    set_to_dummy_if_null(ops, memtype);
+    set_to_dummy_if_null(ops, microcode);
+    set_to_dummy_if_null(ops, physinfo);
+    set_to_dummy_if_null(ops, platform_quirk);
+    set_to_dummy_if_null(ops, machine_memory_map);
+    set_to_dummy_if_null(ops, domain_memory_map);
+    set_to_dummy_if_null(ops, mmu_normal_update);
+    set_to_dummy_if_null(ops, mmu_machphys_update);
+    set_to_dummy_if_null(ops, add_to_physmap);
+#endif
+}
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
new file mode 100644 (file)
index 0000000..d572f99
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  This work is based on the LSM implementation in Linux 2.6.13.4.
+ *
+ *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
+ *
+ *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ */
+
+#include <xen/init.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+
+#include <xsm/xsm.h>
+
+#ifdef XSM_ENABLE
+
+#define XSM_FRAMEWORK_VERSION    "1.0.0"
+
+extern struct xsm_operations dummy_xsm_ops;
+extern void xsm_fixup_ops(struct xsm_operations *ops);
+
+struct xsm_operations *xsm_ops;
+
+static inline int verify(struct xsm_operations *ops)
+{
+    /* verify the security_operations structure exists */
+    if ( !ops )
+        return -EINVAL;
+    xsm_fixup_ops(ops);
+    return 0;
+}
+
+static void __init do_xsm_initcalls(void)
+{
+    xsm_initcall_t *call;
+    call = __xsm_initcall_start;
+    while ( call < __xsm_initcall_end )
+    {
+        (*call) ();
+        call++;
+    }
+}
+
+int __init xsm_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+                    unsigned long initial_images_start)
+{
+    int ret = 0;
+
+    printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
+
+    if ( XSM_MAGIC )
+    {
+        ret = xsm_policy_init(initrdidx, mbi, initial_images_start);
+        if ( ret )
+        {
+            printk("%s: Error initializing policy.\n", __FUNCTION__);
+            return -EINVAL;
+        }
+    }
+
+    if ( verify(&dummy_xsm_ops) )
+    {
+        printk("%s could not verify "
+               "dummy_xsm_ops structure.\n", __FUNCTION__);
+        return -EIO;
+    }
+
+    xsm_ops = &dummy_xsm_ops;
+    do_xsm_initcalls();
+
+    return 0;
+}
+
+int register_xsm(struct xsm_operations *ops)
+{
+    if ( verify(ops) )
+    {
+        printk("%s could not verify "
+               "security_operations structure.\n", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if ( xsm_ops != &dummy_xsm_ops )
+        return -EAGAIN;
+
+    xsm_ops = ops;
+
+    return 0;
+}
+
+
+int unregister_xsm(struct xsm_operations *ops)
+{
+    if ( ops != xsm_ops )
+    {
+        printk("%s: trying to unregister "
+               "a security_opts structure that is not "
+               "registered, failing.\n", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    xsm_ops = &dummy_xsm_ops;
+
+    return 0;
+}
+
+#endif
+
+long do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
+{
+    return __do_xsm_op(op);
+}
+
+
diff --git a/xen/xsm/xsm_policy.c b/xen/xsm/xsm_policy.c
new file mode 100644 (file)
index 0000000..6da6e31
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (C) 2005 IBM Corporation
+ *
+ *  Authors:
+ *  Reiner Sailer, <sailer@watson.ibm.com>
+ *  Stefan Berger, <stefanb@watson.ibm.com>
+ *
+ *  Contributors:
+ *  Michael LeMay, <mdlemay@epoch.ncsc.mil>
+ *  George Coker, <gscoker@alpha.ncsc.mil>
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ *
+ *
+ *  This file contains the XSM policy init functions for Xen.
+ *  This file is based on the ACM functions of the same name.
+ *
+ */
+
+#include <xsm/xsm.h>
+#include <xen/multiboot.h>
+
+char *policy_buffer = NULL;
+u32 policy_size = 0;
+
+int xsm_policy_init(unsigned int *initrdidx, const multiboot_info_t *mbi,
+                           unsigned long initial_images_start)
+{
+    int i;
+    module_t *mod = (module_t *)__va(mbi->mods_addr);
+    int rc = 0;
+    u32 *_policy_start;
+    unsigned long start, _policy_len;
+
+    /*
+     * Try all modules and see whichever could be the binary policy.
+     * Adjust the initrdidx if module[1] is the binary policy.
+     */
+    for ( i = mbi->mods_count-1; i >= 1; i-- )
+    {
+        start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
+#if defined(__i386__)
+        _policy_start = (u32 *)start;
+#elif defined(__x86_64__)
+        _policy_start = maddr_to_virt(start);
+#endif
+        _policy_len   = mod[i].mod_end - mod[i].mod_start;
+
+        if ( (xsm_magic_t)(*_policy_start) == XSM_MAGIC )
+        {
+            policy_buffer = (char *)_policy_start;
+            policy_size = _policy_len;
+
+            printk("Policy len  0x%lx, start at %p.\n",
+                   _policy_len,_policy_start);
+
+            if ( i == 1 )
+                *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
+            break;
+
+        }
+    }
+
+    return rc;
+}